package cn.yunyichina.provider.framework.reflect;

import cn.yunyichina.provider.framework.exception.CallException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 根据方法名和参数动态调用对应的方法
 *
 * @author zhangkewen
 */
public class MethodReflect {

    private static final Logger logger = LoggerFactory.getLogger(MethodReflect.class);

    public static Object invokeMethodGernaral(Object owner, String methodName, Object[] args)
            throws NullPointerException, IllegalAccessException, InvocationTargetException {

        // a.先获取对象所属的类
        Class ownerClass = owner.getClass();
        Method method = null;
        Object result = null;

        // b.获取需要调用的方法
        int methodParamsCount = 0;
        for (Method m : ownerClass.getDeclaredMethods()) {
            if (m.getName().equalsIgnoreCase(methodName)) {
                methodParamsCount = m.getGenericParameterTypes().length;
                method = m;
                break;
            }
        }

        // c.调用该方法
        try {
            if (methodParamsCount == 0) {
                result = method.invoke(owner);
            } else if (methodParamsCount == 2) {
                result = method.invoke(owner, new Object[]{args[0],args[1]});// 调用方法
            }else if (methodParamsCount == 3) {
            	 result = method.invoke(owner, args);// 调用方法
            } else if (methodParamsCount == 1) {
                result = method.invoke(owner, new Object[]{args[0]});// 调用方法
            }
        } catch (NullPointerException e) {
            logger.error("找不到服务[{}].[{}]的方法实现", ownerClass.getName(), methodName);
            throw e;
        } catch (IllegalAccessException e) {
            throw e;
        } catch (InvocationTargetException e) {
            if (CallException.class.getName().equals(e.getTargetException().getClass().getName())) {
                CallException cex = (CallException) e.getTargetException();
                throw cex;
            }
            throw e;
        }

        return result;
    }

}
